mod message_middleware;
mod circuit_breaker;
mod retry;

use async_trait::async_trait;
use futures::future::BoxFuture;
use crate::context::Context;
use crate::message::DynamicMessage;
use crate::errors::SendError;
use std::future::Future;
use std::pin::Pin;

pub use message_middleware::LoggingMiddleware;
pub use circuit_breaker::{CircuitBreaker, CircuitBreakerConfig, CircuitBreakerState};
pub use retry::{RetryMiddleware, ExponentialBackoff};

pub type Next<'a> = Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = Result<(), SendError>> + Send + 'a>> + Send + 'a>;

pub trait Middleware: Send + Sync {
    fn handle<'a>(&'a self, ctx: &'a mut Context, msg: DynamicMessage, next: Next<'a>) -> Pin<Box<dyn Future<Output = Result<(), SendError>> + Send + 'a>>;
}

pub struct MiddlewareChain {
    middlewares: Vec<Box<dyn Middleware>>,
}

impl MiddlewareChain {
    pub fn new() -> Self {
        Self {
            middlewares: Vec::new(),
        }
    }

    pub fn add<M: Middleware + 'static>(&mut self, middleware: M) {
        self.middlewares.push(Box::new(middleware));
    }

    pub fn execute<'a>(&'a self, ctx: &'a mut Context, msg: DynamicMessage) -> Pin<Box<dyn Future<Output = Result<(), SendError>> + Send + 'a>> {
        Box::pin(async move {
            let mut iter = self.middlewares.iter();
            
            fn create_next<'a>(
                iter: &'a mut std::slice::Iter<'a, Box<dyn Middleware>>,
                ctx: &'a mut Context,
                msg: DynamicMessage,
            ) -> Next<'a> {
                Box::new(move || {
                    if let Some(middleware) = iter.next() {
                        middleware.handle(ctx, msg.clone(), create_next(iter, ctx, msg))
                    } else {
                        Box::pin(async move { Ok(()) })
                    }
                })
            }

            let next = create_next(&mut iter, ctx, msg.clone());
            next().await
        })
    }
} 